package cn.bugDance.domain.strategy.service.rule.chain.factory;

import cn.bugDance.domain.strategy.model.entity.RaffleFactorEntity;
import cn.bugDance.domain.strategy.model.entity.StrategyEntity;
import cn.bugDance.domain.strategy.model.valobj.StrategyConstant;
import cn.bugDance.domain.strategy.repository.IStrategyRepository;
import cn.bugDance.domain.strategy.service.rule.chain.IRuleChain;
import cn.bugDance.types.common.Constants;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class RuleChainFactory {

    private IStrategyRepository strategyRepository;
    private ApplicationContext applicationContext;
    private Map<Long, IRuleChain> ruleChainGroup;


    public RuleChainFactory(IStrategyRepository strategyRepository, ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
        this.strategyRepository = strategyRepository;
        ruleChainGroup = new ConcurrentHashMap<>();
    }

    public RuleChainActionEntity openRuleChain(RaffleFactorEntity raffleFactorEntity){
        log.info("【策略领域层-RuleChainFactory】: 规则责任链工厂开启责任执行, strategyId: {}, userId: {}", raffleFactorEntity.getStrategyId(), raffleFactorEntity.getUserId());

        if(ruleChainGroup.get(raffleFactorEntity.getStrategyId()) != null){
            return ruleChainGroup.get(raffleFactorEntity.getStrategyId()).action(raffleFactorEntity);
        }

        StrategyEntity strategyEntity = strategyRepository.queryStrategyByStrategyId(raffleFactorEntity.getStrategyId());
        String ruleModelStr = strategyEntity.getRuleModels();
        if(StringUtils.isBlank(ruleModelStr)){
            IRuleChain backStopChain = applicationContext.getBean(StrategyConstant.StrategyRule.RULE_BACK_STOP, IRuleChain.class);
            ruleChainGroup.put(raffleFactorEntity.getStrategyId(), backStopChain);
            return backStopChain.action(raffleFactorEntity);
        }

        String[] ruleModels = ruleModelStr.split(Constants.SPLIT);
        IRuleChain root = null;
        IRuleChain curr = null;
        for(String ruleModel : ruleModels){
            IRuleChain next = applicationContext.getBean(ruleModel, IRuleChain.class);
            if(null == root){
                root = next;
                curr = root;
            }
            else{
                curr.appendNext(next);
                curr = curr.getNext();
            }
        }

        if(curr != null){
            IRuleChain backStopChain = applicationContext.getBean(StrategyConstant.StrategyRule.RULE_BACK_STOP, IRuleChain.class);
            curr.appendNext(backStopChain);
        }
        else{
            IRuleChain backStopChain = applicationContext.getBean(StrategyConstant.StrategyRule.RULE_BACK_STOP, IRuleChain.class);
            root = backStopChain;
        }

        ruleChainGroup.put(raffleFactorEntity.getStrategyId(), root);
        return root.action(raffleFactorEntity);
    }


    /**
     * 责任链结果
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class RuleChainActionEntity{
        private Long strategyId;
        private Integer awardId;
    }
}
